#pragma once
#include <ntddk.h>
#include <mp.h>

#pragma warning(push)
#pragma warning(disable:4201) // nameless struct/union
#pragma warning(disable:4214) // bit field types other than int
#include <wsk.h>
#pragma warning(pop)

#define SOCKET_ERROR -1

#define RELATIVE(wait) (-(wait))

#define NANOSECONDS(nanos)   \
     (((signed __int64)(nanos)) / 100L)

#define MICROSECONDS(micros) \
     (((signed __int64)(micros)) * NANOSECONDS(1000L))

#define MILLISECONDS(milli)  \
     (((signed __int64)(milli)) * MICROSECONDS(1000L))

#define SECONDS(seconds)	 \
     (((signed __int64)(seconds)) * MILLISECONDS(1000L))

#define HTONS(n) (((((unsigned short)(n) & 0xFFu  )) << 8) | \
                   (((unsigned short)(n) & 0xFF00u) >> 8))

NTSTATUS NTAPI SocketsInit();
VOID NTAPI SocketsDeinit();

PWSK_SOCKET
NTAPI
  CreateSocket(
    __in ADDRESS_FAMILY	AddressFamily,
    __in USHORT			SocketType,
    __in ULONG			Protocol,
    __in ULONG			Flags
    );

NTSTATUS
NTAPI
  CloseSocket(
	__in PWSK_SOCKET WskSocket
	);

NTSTATUS
NTAPI
  Connect(
	__in PWSK_SOCKET	WskSocket,
	__in PSOCKADDR		RemoteAddress
	);

PWSK_SOCKET
NTAPI
  SocketConnect(
	__in USHORT		SocketType,
	__in ULONG		Protocol,
	__in PSOCKADDR	RemoteAddress,
	__in PSOCKADDR	LocalAddress
	);

LONG
NTAPI
  Send(
	__in PWSK_SOCKET	WskSocket,
	__in PVOID			Buffer,
	__in ULONG			BufferSize,
	__in ULONG			Flags
	);

LONG
NTAPI
  SendTo(
	__in PWSK_SOCKET	WskSocket,
	__in PVOID			Buffer,
	__in ULONG			BufferSize,
    __in_opt PSOCKADDR	RemoteAddress
	);

LONG
NTAPI
  Receive(
	__in  PWSK_SOCKET	WskSocket,
	__out PVOID			Buffer,
	__in  ULONG			BufferSize,
	__in  ULONG			Flags
	);

LONG
NTAPI
  ReceiveFrom(
	__in  PWSK_SOCKET	WskSocket,
	__out PVOID			Buffer,
	__in  ULONG			BufferSize,
	__out_opt PSOCKADDR	RemoteAddress,
    __out_opt PULONG	ControlFlags
	);


NTSTATUS
NTAPI
  Bind(
	__in PWSK_SOCKET	WskSocket,
	__in PSOCKADDR		LocalAddress
	);

PWSK_SOCKET
NTAPI
  Accept(
	__in PWSK_SOCKET	WskSocket,
	__out_opt PSOCKADDR	LocalAddress,
	__out_opt PSOCKADDR	RemoteAddress
   );

typedef struct _UDP_HEADER {
    unsigned short SourcePort;
    unsigned short DestinPort;
    unsigned short Length;
    unsigned short CheckSum;
} UDP_HEADER, PUDP_HEADER;

typedef struct _IP_HEADER {
    unsigned int Reserved;
    unsigned int Reserved2;
    unsigned int Protocol;
    unsigned int IPSource;
    unsigned int IPDest;
}IP_HEADER, *PIP_HEADER;

typedef struct _ETHERNET_ {
    unsigned char DMAC[6];
    unsigned char SMAC[6];
    //unsigned short IPType;
    IP_HEADER ip_head;
    UDP_HEADER udp_head;
}ETHERNET,*PETHERNET;

NTSTATUS InitSocketsExt();
VOID DeInitSocketExt();

NTSTATUS CreateSocketExt();
NTSTATUS SocketCompletionExt ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) ;
NTSTATUS BindCompletionExt(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
NTSTATUS MyWskReceiveFromEventExt(PVOID SocketContext, unsigned long Flags, PWSK_DATAGRAM_INDICATION DataIndication);

